package top.lyjwn.todo.conf;

import com.alibaba.fastjson2.JSONObject;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.exception.StatusException;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.Filter;
import org.noear.solon.core.handle.FilterChain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smartboot.http.common.utils.StringUtils;
import top.lyjwn.todo.ex.TodoException;
import top.lyjwn.todo.template.R;
import top.lyjwn.todo.utils.ContextUtil;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Component
public class AppFilter implements Filter {

    static final Logger logger = LoggerFactory.getLogger("HTTP_LOG");

    static final Logger log = LoggerFactory.getLogger(AppFilter.class);

    @Override
    public void doFilter(Context ctx, FilterChain chain)  {
//        if (ctx.mainHandler() == null) {
//            ctx.output(JSONObject.toJSONString(R.init().error(404, "未找到该资源")));
//            return;
//        }
        String requestData = null;
        //1.开始计时（用于计算响应时长）
        long start = System.currentTimeMillis();
        try {
            requestData = getRequestData(ctx);
            //3.执行处理
            chain.doFilter(ctx);
            //3.2.未处理
//            if (!ctx.getHandled() && ctx.result == null) {
//                String res = JSONObject.toJSONString(R.init().error(405, "该请求未被处理"));
//                ctx.output(res);
//                ctx.result = res;
//            } else if (ctx.result == null) {
//                //3.3.404状态的定制（也可对别的状态处理）
//                switch (ctx.status()) {
//                    case 404:
//                        String res = JSONObject.toJSONString(R.init().error(404, "未找到对应资源"));
//                        ctx.output(res);
//                        ctx.result = res;
//                        ctx.setHandled(true);
//                        break;
//                }
//            }
            //4.记录响应数据日志
        } catch (TodoException e) {
            //todo异常的话，直接输出msg
            String rstr = JSONObject.toJSONString(R.init().error(500, e.getMessage()));
            ContextUtil.handledContext(ctx, rstr);
            //log.error("{}", e.getMessage(), e);
        } catch (NoClassDefFoundError e) {
            String rstr = JSONObject.toJSONString(R.init().error(500, "json解析失败" + e.getMessage()));
            ContextUtil.handledContext(ctx, rstr);
            log.error("{}", e.getMessage(), e);
        } catch (StatusException e) {
            //4.异常捕捉与控制（并标为500错误）
            //ctx.status(500);
            if (!ctx.getHandled())
            {
                String rstr = "";
                switch (e.getCode()) {
                    case 400 -> rstr = JSONObject.toJSONString(R.init().error(400, e.getCause().getMessage()));
                    default -> rstr = JSONObject.toJSONString(R.init().error(500, e.getClass().getSimpleName()));
                }
                ContextUtil.handledContext(ctx, rstr);
            }
            log.info("{}", e.getMessage());
        }
        catch (Exception e) {
            String rstr = JSONObject.toJSONString(R.init().error(500, e.getClass().getSimpleName()));
            ContextUtil.handledContext(ctx, rstr);
            log.error("{}", e.getMessage(), e);
        } catch (Throwable e) {
            //4.异常捕捉与控制（并标为500错误）
            //ctx.status(500);
            String rstr = JSONObject.toJSONString(R.init().error(500, e.getClass().getSimpleName()));
            ContextUtil.handledContext(ctx, rstr);
            log.error("{}", e.getMessage(), e);
        } finally {
            if (!ctx.getHandled()) {
                String rstr = JSONObject.toJSONString(R.init().error(404, "Unprocessed requests"));
                ContextUtil.handledContext(ctx, rstr);
            }
            //5.获得接口响应时长
            long times = System.currentTimeMillis() - start;
            logger.info("Civil time：{},\r\n Ip: {},\r\n Path: {},\r\n Request data: {},\r\n Response data: {} \r\n", times, ctx.realIp(), ctx.path(), requestData, getResponseData(ctx.result)); //getResponseData 需要自己写，把 ctx 里的请求数据转为 string

        }
    }

    private String getRequestData(Context ctx) {
//        String paramsData = "";
//        Map<String, List<String>> paramsMap = ctx.paramsMap();
//        if (!paramsMap.isEmpty()) {
//            paramsData = JSONObject.toJSONString(paramsMap);
//        }
        String bodyData = "";
        try {
            bodyData = ctx.body();
        } catch (IOException e) {
            e.printStackTrace();
        }
        String data = "";
//        if (!(StringUtils.isBlank(paramsData) || StringUtils.isBlank(bodyData))) {
//            data = "[ params: ${paramsData} ],[body: ${bodyData}]";
//        } else if (!StringUtils.isBlank(paramsData)) {
//            data = "[ params: ${paramsData} ]";
//        } else
            if (!StringUtils.isBlank(bodyData)) {
            data = "[ body: ${bodyData} ]";
        } else {
            return null;
        }

//        return data.replace("${paramsData}", paramsData).replace("${bodyData}", bodyData);
        return data.replace("${bodyData}", bodyData);
    }

    private String getResponseData(Object result) {
        return JSONObject.toJSONString(result);
    }
}